﻿using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using CustomerList.Model;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Threading;
using MyMeetup.Entities;
using MyMeetup.Helpers;

namespace MyMeetup.ViewModels
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// You can also use Blend to data bind with the tool's support.
    /// </para>
    /// <para>
    /// See http://www.galasoft.ch/mvvm/getstarted
    /// </para>
    /// </summary>
    public class GroupPageViewModel : ViewModelBase
    {
        private readonly DataService _dataService;
        private readonly INavigationService _navigationService;
        //public Group Model { get; set; }

        private const int EventsPerPage = 15;
        private int _currentPage = 0;

        public RelayCommand<Event> RsvpYesCommand { get; private set; }
        public RelayCommand<Event> RsvpNoCommand { get; private set; }
        public RelayCommand<Event> CheckinCommand { get; private set; } 
        public RelayCommand<Event> EventPageCommand { get; private set; }
        public RelayCommand<Album> AlbumPageCommand { get; private set; }
        public RelayCommand ShowPastEventsCommand { get; private set; }
        public RelayCommand LoadedCommand { get; private set; }
        

        /// <summary>
        /// Initializes a new instance of the GroupPageViewModel class.
        /// </summary>
        public GroupPageViewModel()
        {
            _dataService = new DataService();
            _navigationService = new NavigationService();

            LoadedCommand = new RelayCommand(LoadPage);
            EventPageCommand = new RelayCommand<Event>(GoToEventPage);
            AlbumPageCommand = new RelayCommand<Album>(GoToAlbumPage);
            CheckinCommand = new RelayCommand<Event>(CheckinToEvent);
            RsvpYesCommand = new RelayCommand<Event>(SubmitRsvpYes);
            RsvpNoCommand = new RelayCommand<Event>(SubmitRsvpNo);
            ShowPastEventsCommand = new RelayCommand(ShowPastEvents);

            DispatcherHelper.Initialize();

            Messenger.Default.Register<PropertyChangedMessage<IGroup>>(this,
                                                                         (action) => UpdateGroup(action.NewValue));
            ////if (IsInDesignMode)
            ////{
            ////    // Code runs in Blend --> create design time data.
            ////}
            ////else
            ////{
            ////    // Code runs "for real": Connect to service, etc...
            ////}
        }

        private void UpdateGroup(IGroup group)
        {
            Model = group;
        }


        private void ErrorCallbackInternal(RequestError e)
        {
            ResponseHelper.ErrorCallback(e);
        }

        public void LoadPage()
        {
            Organizer = null;

            _dataService.GetGroupPhoto(Model.id, SetBackgroundImage, BackgroundImageErrorCallback);

            _dataService.GetEventsForGroup(Model.id, EventsPerPage, _currentPage, (e) => ShowEvents(e, false), ErrorCallbackInternal);
            
            _dataService.GetGroupPhotoAlbums(Model.id, (x) => { PhotoAlbums = x;}, ErrorCallbackInternal);

            ShowPastEventsVisibility = Visibility.Visible;

            if (Model.self == null)
            {
                _dataService.GetMember(Model.organizer.member_id, (x) => { Organizer = new ProfileAdapter(x);}, ErrorCallbackInternal);
            }
            else
            {
                _dataService.GetMemberProfile(Model.organizer.member_id, Model.id, (x) => { Organizer = x;}, ErrorCallbackInternal);
            }
        }


        private void ShowEvents(ObservableCollection<Event> events, bool append)
        {
            if (events.Count < EventsPerPage)
                ShowPastEventsVisibility = Visibility.Collapsed;

            //if (GroupEvents == null || GroupEvents.Count == 0)
            //    GroupEvents = events;
            //else
            if (!append) GroupEvents = events;
            else
            {
                foreach (var e in events)
                {
                    GroupEvents.Add(e);
                }
            }
        }
        
        private void ShowPastEvents()
        {
           _dataService.GetEventsForGroup(Model.id, EventsPerPage, ++_currentPage, (e) => ShowEvents(e, true), ShowPastEventsErrorCallback); 
        }
        
        

        private void ShowPastEventsErrorCallback(RequestError e)
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() => ShowPastEventsVisibility = Visibility.Visible); 
            ErrorCallbackInternal(e); 
        }



        private void SetBackgroundImage(Photo photo)
        {
            if (photo == null)
            {
                return;
            } // sometimes you can't get the photo if you're not a member of the group

            BackgroundImageUrl = photo.photo_link;

            var brush = new ImageBrush
            {
                ImageSource = new BitmapImage(new Uri(photo.photo_link, UriKind.Absolute)),
                Stretch = Stretch.UniformToFill,
                //Opacity = .3
            };
            BackgroundImage = brush;
        }

        private void BackgroundImageErrorCallback(RequestError e)
        {
            DispatcherHelper.CheckBeginInvokeOnUI(()=>BackgroundImage = new ImageBrush(){ImageSource = new BitmapImage()});
            ErrorCallbackInternal(e);
        }




        private void CheckinToEvent(Event selectedEvent)
        {
            var checkinHelper = new CheckinHelper(_dataService, _navigationService);
            checkinHelper.CheckinToEvent(selectedEvent.id);
        }


        private void SubmitRsvpYes(Event selectedEvent)
        {
            SubmitRsvp(selectedEvent, RSVPType.Yes);
        }

        private void SubmitRsvpNo(Event selectedEvent)
        {
            SubmitRsvp(selectedEvent, RSVPType.No);
        }

        private void SubmitRsvp(Event selectedEvent, RSVPType response)
        {
            var rsvpHelper = new RsvpHelper(_dataService, _navigationService);
            rsvpHelper.SubmitRsvp(selectedEvent.id, response, (rsvpResponse) => selectedEvent.self.rsvp.response = rsvpResponse.response);
        }


        private void GoToAlbumPage(Album selectedAlbum)
        {
            _navigationService.NavigateTo(new Uri("/AlbumPage.xaml", UriKind.Relative));
        }

        private void GoToEventPage(Event selectedEvent)
        {
            _navigationService.NavigateTo(new Uri("/EventPage.xaml", UriKind.Relative));
        }


       


        /// <summary>
        /// The <see cref="Model" /> property's name.
        /// </summary>
        public const string ModelPropertyName = "Model";

        private IGroup _model;

        /// <summary>
        /// Gets the Model property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public IGroup Model
        {
            get
            {
                return _model;
            }

            set
            {
                if (_model == value)
                {
                    return;
                }

                var oldValue = _model;
                _model = value;

               

                // Update bindings, no broadcast
                RaisePropertyChanged(ModelPropertyName);
            }
        }


        /// <summary>
        /// The <see cref="ShowPastEventsVisibility" /> property's name.
        /// </summary>
        public const string ShowPastEventsVisibilityPropertyName = "ShowPastEventsVisibility";

        private Visibility _showPastEventsVisibility = Visibility.Visible;

        /// <summary>
        /// Gets the ShowPastEventsVisibility property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public Visibility ShowPastEventsVisibility
        {
            get
            {
                return _showPastEventsVisibility;
            }

            set
            {
                if (_showPastEventsVisibility == value)
                {
                    return;
                }

                var oldValue = _showPastEventsVisibility;
                _showPastEventsVisibility = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(ShowPastEventsVisibilityPropertyName);
            }
        }


        /// <summary>
        /// The <see cref="SelectedAlbum" /> property's name.
        /// </summary>
        public const string SelectedAlbumPropertyName = "SelectedAlbum";

        private Album _selectedAlbum;

        /// <summary>
        /// Gets the SelectedAlbum property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public Album SelectedAlbum
        {
            get
            {
                return _selectedAlbum;
            }

            set
            {
                if (_selectedAlbum == value)
                {
                    return;
                }

                var oldValue = _selectedAlbum;
                _selectedAlbum = value;

                // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
                RaisePropertyChanged(SelectedAlbumPropertyName, oldValue, value, true);
            }
        }


        /// <summary>
        /// The <see cref="SelectedEvent" /> property's name.
        /// </summary>
        public const string SelectedEventPropertyName = "SelectedEvent";

        private Event _selectedEvent;

        /// <summary>
        /// Gets the SelectedEvent property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public Event SelectedEvent
        {
            get
            {
                return _selectedEvent;
            }

            set
            {
                if (_selectedEvent == value)
                {
                    return;
                }

                var oldValue = _selectedEvent;
                _selectedEvent = value;

                // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
                RaisePropertyChanged(SelectedEventPropertyName, oldValue, value, true);
            }
        }

        /// <summary>
        /// The <see cref="Organizer" /> property's name.
        /// </summary>
        public const string OrganizerPropertyName = "Organizer";

        private IProfile _organizer;

        /// <summary>
        /// Gets the Organizer property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public IProfile Organizer
        {
            get
            {
                return _organizer;
            }

            set
            {
                if (_organizer == value)
                {
                    return;
                }

                var oldValue = _organizer;
                _organizer = value;


                // Update bindings, no broadcast
                RaisePropertyChanged(OrganizerPropertyName);
            }
        }


        /// <summary>
        /// The <see cref="PhotoAlbums" /> property's name.
        /// </summary>
        public const string PhotoAlbumsPropertyName = "PhotoAlbums";

        private ObservableCollection<Album> _photoAlbums;

        /// <summary>
        /// Gets the PhotoAlbums property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ObservableCollection<Album> PhotoAlbums
        {
            get
            {
                return _photoAlbums;
            }

            set
            {
                if (_photoAlbums == value)
                {
                    return;
                }

                var oldValue = _photoAlbums;
                _photoAlbums = value;

                // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
                RaisePropertyChanged(PhotoAlbumsPropertyName, oldValue, value, true);
            }
        }


        /// <summary>
        /// The <see cref="BackgroundImage" /> property's name.
        /// </summary>
        public const string BackgroundImagePropertyName = "BackgroundImage";

        private ImageBrush _backgroundImage;

        /// <summary>
        /// Gets the BackgroundImage property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ImageBrush BackgroundImage
        {
            get
            {
                return _backgroundImage;
            }

            set
            {
                if (_backgroundImage == value)
                {
                    return;
                }

                _backgroundImage = value;


                // Update bindings, no broadcast
                RaisePropertyChanged(BackgroundImagePropertyName);

            }
        }

        /// <summary>
        /// The <see cref="BackgroundImageUrl" /> property's name.
        /// </summary>
        public const string BackgroundImageUrlPropertyName = "BackgroundImageUrl";

        private string _backgroundImageUrl = "";

        /// <summary>
        /// Gets the BackgroundImageUrl property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public string BackgroundImageUrl
        {
            get
            {
                return _backgroundImageUrl;
            }

            set
            {
                if (_backgroundImageUrl == value)
                {
                    return;
                }

                var oldValue = _backgroundImageUrl;
                _backgroundImageUrl = value;

               
                // Update bindings, no broadcast
                RaisePropertyChanged(BackgroundImageUrlPropertyName);

            }
        }

        /// <summary>
        /// The <see cref="GroupEvents" /> property's name.
        /// </summary>
        public const string GroupEventsPropertyName = "GroupEvents";

        private ObservableCollection<Event> _groupEvents;

        /// <summary>
        /// Gets the GroupEvents property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ObservableCollection<Event> GroupEvents
        {
            get
            {
                return _groupEvents;
            }

            set
            {
                if (_groupEvents == value)
                {
                    return;
                }

                _groupEvents = value;


                // Update bindings, no broadcast
                RaisePropertyChanged(GroupEventsPropertyName);
            }
        }


    }
}